package com.bfly.mall.user.controller;

import com.bfly.common.ResponseUtil;
import com.bfly.common.page.Pager;
import com.bfly.common.util.DataConvertUtils;
import com.bfly.core.base.controller.BaseController;
import com.bfly.core.base.entity.ResponseData;
import com.bfly.core.context.PagerThreadLocal;
import com.bfly.core.enums.SysError;
import com.bfly.core.exception.ServiceResponseException;
import com.bfly.core.security.ActionModel;
import com.bfly.mall.user.dto.UserFormDTO;
import com.bfly.mall.user.dto.UserListDTO;
import com.bfly.mall.user.entity.User;
import com.bfly.mall.user.service.IUserService;
import com.bfly.mall.wechat.entity.WeChatMp;
import com.bfly.mall.wechat.mp.dto.WeChatMpUserInfo;
import com.bfly.mall.wechat.mp.dto.WeChatMpUserInfoRequest;
import com.bfly.mall.wechat.mp.dto.WeChatMpUserSynResponse;
import com.bfly.mall.wechat.mp.service.WeChatMPAPi;
import com.bfly.mall.wechat.service.IWeChatMpService;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.annotations.Param;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.task.TaskExecutor;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 会员
 *
 * @author 长沙商脉科技有限公司
 * @date 2020/9/18 14:40
 */
@RestController
@RequestMapping(value = "/manage/user")
public class UserController extends BaseController {

    private Logger logger = LoggerFactory.getLogger(UserController.class);
    @Autowired
    private IUserService userService;
    @Autowired
    private IWeChatMpService weChatMpService;
    @Autowired
    @Qualifier("taskExecutor")
    private TaskExecutor taskExecutor;


    /**
     * 会员列表
     *
     * @author 长沙商脉科技有限公司
     * @date 2020/9/16 18:51
     */
    @GetMapping(value = "/list")
    public void list(HttpServletResponse response, HttpServletRequest request) {
        PagerThreadLocal.set(request);
        String enable = request.getParameter("enable");
        String gender = request.getParameter("gender");
        String platform = request.getParameter("platform");
        String platformId = request.getParameter("platformId");
        String nickName = request.getParameter("nickName");

        Map<String, Object> exactQuery = new HashMap<>(3);
        Map<String, String> unExactQuery = new HashMap<>(1);
        if (StringUtils.isNotBlank(enable)) {
            exactQuery.put("is_enable", DataConvertUtils.convertToBoolean(enable));
        }
        if (StringUtils.isNotBlank(gender)) {
            exactQuery.put("gender", DataConvertUtils.convertToInteger(gender));
        }
        if (StringUtils.isNotBlank(platform)) {
            exactQuery.put("platform", DataConvertUtils.convertToInteger(platform));
        }
        if (StringUtils.isNotBlank(platformId)) {
            exactQuery.put("platform_id", DataConvertUtils.convertToInteger(platformId));
        }
        if (StringUtils.isNotBlank(nickName)) {
            unExactQuery.put("nick_name", nickName);
        }
        Pager<User> pager = userService.getPage(exactQuery, unExactQuery, null);
        Pager<UserListDTO> dtoPager = new Pager<>(pager.getPageNo(), pager.getPageSize(), pager.getTotalCount());

        if (pager.getData() != null) {
            List<UserListDTO> list = new ArrayList<>();
            for (User user : pager.getData()) {
                UserListDTO dto = new UserListDTO();
                BeanUtils.copyProperties(user, dto);
                list.add(dto);
            }
            dtoPager.setData(list);
        }
        ResponseUtil.writeJson(response, ResponseData.getSuccess(dtoPager));
    }

    /**
     * 修改用户状态
     *
     * @author 长沙商脉科技有限公司
     * @date 2020/9/18 15:39
     */
    @GetMapping(value = "/active")
    @ActionModel(value = "修改用户状态")
    public void activeUser(HttpServletResponse response, @Param("userId") int userId, @Param("enable") boolean enable) {
        userService.activeUser(userId, enable);
        ResponseUtil.writeJson(response, ResponseData.getSuccess(""));
    }

    /**
     * 编辑会员信息
     *
     * @author 长沙商脉科技有限公司
     * @date 2020/9/17 13:26
     */
    @PostMapping(value = "/edit")
    @ActionModel(value = "编辑会员信息")
    public void edit(HttpServletResponse response, @Valid @RequestBody UserFormDTO formDTO, BindingResult result) {
        validData(result);
        userService.edit(formDTO);
        ResponseUtil.writeJson(response, ResponseData.getSuccess(""));
    }

    /**
     * 删除会员信息
     *
     * @author 长沙商脉科技有限公司
     * @date 2020/9/17 13:27
     */
    @PostMapping(value = "/delete")
    @ActionModel(value = "删除会员信息")
    public void delete(HttpServletResponse response, @RequestBody Integer... userIds) {
        userService.remove(userIds);
        ResponseUtil.writeJson(response, ResponseData.getSuccess(""));
    }

    /**
     * 同步公众号用户
     *
     * @author 长沙商脉科技有限公司
     * @date 2021/1/5 19:30
     */
    @GetMapping(value = "/mp/sync")
    @ActionModel(value = "同步公众号用户信息")
    public void syncMpUser(HttpServletResponse response, @RequestParam("appId") String appId) {
        WeChatMp mp = weChatMpService.getWeChatMp(appId);
        if (mp == null) {
            throw new ServiceResponseException(SysError.PARAM_ERROR, "不存在的公众号信息!");
        }
        getSyncMpUser(mp, "");
        ResponseUtil.writeJson(response,ResponseData.getSuccess(""));
    }

    private void getSyncMpUser(WeChatMp mp, String nextOpenId) {
        taskExecutor.execute(() -> {
            WeChatMpUserSynResponse result = WeChatMPAPi.syncMpUser(mp.getAppId(), mp.getAppSecret(), nextOpenId);
            if (StringUtils.isBlank(result.getNext_openid())) {
                // 拉取完毕
                logger.info(String.format("同步微信公众号【%s】用户完毕!", mp.getName()));
            } else {
                // 如果还有未拉取完毕的 重新发起拉取用户任务
                syncMpUserToDB(mp, result.getData().getOpenid());
                getSyncMpUser(mp, result.getNext_openid());
            }
        });
    }

    private void syncMpUserToDB(WeChatMp mp, List<String> openIds) {
        if (openIds.isEmpty()) {
            return;
        }
        List<WeChatMpUserInfoRequest> list = new ArrayList<>();
        // 每100个拉取详细信息
        int cutLength = openIds.size() > 100 ? 10 : openIds.size();
        List<String> cutOpenIds = openIds.subList(0, cutLength);
        cutOpenIds.forEach(openId -> {
            WeChatMpUserInfoRequest request = new WeChatMpUserInfoRequest(openId);
            list.add(request);
        });
        List<WeChatMpUserInfo> userInfos = WeChatMPAPi.getMpUserInfo(mp.getAppId(), mp.getAppSecret(), list);
        userInfos.forEach(userInfo -> {
            userService.merge(mp.getId(),userInfo);
        });
        cutOpenIds = openIds.subList(cutLength, openIds.size());
        syncMpUserToDB(mp, cutOpenIds);
    }
}
